<?php


namespace app\common\service\promotion;

use app\common\model\agent\PromotionBillModel;
use app\common\service\promotion\PromotionRoleService;
use app\common\service\system\Exception;
use app\common\service\promotion\PromotionUserLogService;
use app\common\service\system\SettingService;
use think\facade\Config;
use think\facade\Db;
use think\facade\Validate;
use app\common\cache\promotion\PromotionUserCache;
use app\common\model\promotion\PromotionMenuModel;
use app\common\model\promotion\PromotionUserModel;
use app\common\service\promotion\PromotionSettingService;
use app\common\service\promotion\PromotionUserTokenService;
use app\common\service\utils\Utils;
use hg\apidoc\annotation as Apidoc;

/**
 * 用户管理
 */
class PromotionUserService
{
    /**
     * 添加修改字段
     * @var array
     */
    public static $edit_field = [
        'promotion_user_id/d'   => '',
        'avatar_id/d' => 0,
        'number/s'    => '',
        'nickname/s'  => '',
        'username/s'  => '',
        'phone/s'     => '',
        'email/s'     => '',
        'remark/s'    => '',
        'sort/d'      => 250,
        'pid/d'      => 0,
        'level/d'      => 0,
        'commission_ratio/d'      => 0,
        'p_commission_ratio/d'      => 0,
    ];

    /**
     * 用户列表
     *
     * @param array  $where 条件
     * @param int    $page  页数
     * @param int    $limit 数量
     * @param array  $order 排序
     * @param string $field 字段
     * 
     * @return array 
     */
    public static function list($where = [], $page = 1, $limit = 10,  $order = [], $field = '')
    {
        $model = new PromotionUserModel();
        $pk = $model->getPk();
        $group = 'm.' . $pk;

        if (empty($field)) {
            $field = $group . ',avatar_id,number,nickname,username,sort,is_super,is_disable,create_time,update_time,login_time,pid,level,commission_ratio,p_commission_ratio,remark';
        }
        if (empty($order)) {
            $order = ['sort' => 'desc', $group => 'desc'];
        }

        if (promotion_user_hide_where()) {
            $where[] = promotion_user_hide_where('m.promotion_user_id');
        }

        $model = $model->alias('m');
        foreach ($where as $wk => $wv) {
            if ($wv[0] == 'role_ids' && is_array($wv[2])) {
                $model = $model->join('promotion_user_attributes r', 'm.promotion_user_id=r.promotion_user_id')->where('r.role_id', $wv[1], $wv[2]);
                unset($where[$wk]);
            }
        }
        $where = array_values($where);

        $with     = [];
        $append   = [];
        $hidden   = [];
        $field_no = [];
        if (strpos($field, 'avatar_id') !== false) {
            $with[]   = $hidden[] = 'avatar';
            $append[] = 'avatar_url';
        }
        $fields = explode(',', $field);
        foreach ($fields as $k => $v) {
            if (in_array($v, $field_no)) {
                unset($fields[$k]);
            }
        }
        $field = implode(',', $fields);

        $count = $model->where($where)->group($group)->count();
        $pages = 0;
        if ($page > 0) {
            $model = $model->page($page);
        }
        if ($limit > 0) {
            $model = $model->limit($limit);
            $pages = ceil($count / $limit);
        }
        $list = $model->field($field)->where($where)
            ->with($with)->append($append)->hidden($hidden)
            ->order($order)->group($group)->select()->toArray();
        foreach ($list as $key=>$val){
            //获取下级推广员id
            $ids = self::getAllDescendants($val['promotion_user_id']);
            array_push($ids,$val['promotion_user_id']);
             $merchant_ids = Db::name('merchant')->whereIn('promotion_user_id',$ids)
                ->where('is_disable',0)
                ->where('is_delete',0)
                ->column('id');
            $list[$key]['merchant_count'] =count($merchant_ids);
            $merchant_ids = array_column($merchant_ids,'id');
            $merchant_str =0;
            if($merchant_ids){
                $merchant_str = implode(',',$merchant_ids);
            }
            //订单数
            $sql = <<<SQL
                SELECT
                  SUM(CASE WHEN status IN (3, 4, 5, 6) THEN 1 ELSE 0 END) AS open_num,
                  SUM(CASE WHEN status = 7 THEN 1 ELSE 0 END) AS success_num
                FROM
                  ya_shop_order
                WHERE
                    is_delete=0 AND merchant_id IN({$merchant_str})
                SQL;
            $order =  Db::query($sql);
            $list[$key]['open_num'] = $order[0]['open_num']??0;
            $list[$key]['success_num'] = $order[0]['success_num']??0;
        }
        return compact('count', 'pages', 'page', 'limit', 'list');
    }

    /**
     * 推广员列表
     *
     * @param string $type  tree树形，list列表
     * @param array  $where 条件
     * @param array  $order 排序
     * @param string $field 字段
     *
     * @return array
     */
    public static function tree_list($type = 'tree', $where = [], $order = [], $field = '')
    {
        $model = new PromotionUserModel();
        $pk = $model->getPk();
        $group = 'm.' . $pk;
        if (empty($field)) {
            $field = $group . ',avatar_id,number,nickname,username,sort,is_super,is_disable,create_time,update_time,login_time,pid,level,commission_ratio,p_commission_ratio,balance,remark';
        }
        if (empty($order)) {
            $order = ['sort' => 'desc', $pk => 'asc'];
        }
        if (promotion_user_hide_where()) {
            $where[] = promotion_user_hide_where('m.promotion_user_id');
        }

        $model = $model->alias('m');
        foreach ($where as $wk => $wv) {
            if ($wv[0] == 'role_ids' && is_array($wv[2])) {
                $model = $model->join('promotion_user_attributes r', 'm.promotion_user_id=r.promotion_user_id')->where('r.role_id', $wv[1], $wv[2]);
                unset($where[$wk]);
            }
        }
        $where = array_values($where);

        $key = where_cache_key($type, $where, $order, $field);
        $data = PromotionUserCache::get($key);
        if (empty($data)) {
            $with     = ['roles'];
            $append   = ['role_names'];
            $hidden   = ['roles'];
            $field_no = [];
            if (strpos($field, 'avatar_id') !== false) {
                $with[]   = $hidden[] = 'avatar';
                $append[] = 'avatar_url';
            }
            $fields = explode(',', $field);
            foreach ($fields as $k => $v) {
                if (in_array($v, $field_no)) {
                    unset($fields[$k]);
                }
            }
            $field = implode(',', $fields);
            $data = $model->field($field)->where($where)
                ->with($with)->append($append)->hidden($hidden)
                ->order($order)->group($group)->select()->toArray();
            if ($type == 'tree') {
                $data = array_to_tree($data, $pk, 'pid');
            }
            PromotionUserCache::set($key, $data);
        }
        return $data;
    }

    /**
     * 用户信息
     *
     * @param int  $id   用户id
     * @param bool $exce 不存在是否抛出异常
     * @param bool $role 是否返回角色信息
     * 
     * @return array|Exception
     */
    public static function info($id, $exce = true, $role = false)
    {
        $info = PromotionUserCache::get($id);
        if (empty($info)) {
            $model = new PromotionUserModel();

            $info = $model->find($id);
            if (empty($info)) {
                if ($exce) {
                    exception('用户不存在：' . $id);
                }
                return [];
            }
            $info = $info
                ->append(['avatar_url', 'dept_ids', 'post_ids', 'role_ids'])
                ->hidden(['avatar', 'depts', 'posts', 'roles'])
                ->toArray();

            $PromotionMenuModel = new PromotionMenuModel();
            $MenuPk = $PromotionMenuModel->getPk();

            if (user_is_super($id)) {
                $menu      = $PromotionMenuModel->field($MenuPk . ',menu_url')->where([where_delete()])->select()->toArray();
                $menu_ids  = array_column($menu, 'menu_id');
                $menu_urls = array_filter(array_column($menu, 'menu_url'));
            } elseif ($info['is_super'] == 1) {
                $menu      = $PromotionMenuModel->field($MenuPk . ',menu_url')->where(where_disdel())->select()->toArray();
                $menu_ids  = array_column($menu, 'menu_id');
                $menu_urls = array_filter(array_column($menu, 'menu_url'));
            } else {
                $role_menu_ids   = PromotionRoleService::menu_ids($info['role_ids'], where_disdel());
                $unauth_menu_ids = PromotionMenuService::unauthList('id');
                $menu_ids        = array_merge($role_menu_ids, $unauth_menu_ids);
                $menu_urls       = $PromotionMenuModel->where('menu_id', 'in', $menu_ids)->where(where_disdel())->column('menu_url');
                $menu_urls       = array_filter($menu_urls);
            }

            if (empty($menu_ids)) {
                $menu_ids = [];
            } else {
                foreach ($menu_ids as $k => $v) {
                    $menu_ids[$k] = (int) $v;
                }
            }

            $menu_is_unlogin = Config::get('promotion.menu_is_unlogin', []);
            $menu_is_unauth  = Config::get('promotion.menu_is_unauth', []);
            $unlogin_unauth  = array_merge($menu_is_unlogin, $menu_is_unauth);
            $menu_urls       = array_unique(array_merge($menu_urls, $unlogin_unauth));

            $info['roles']    = array_values($menu_urls);
            $info['menus']    = PromotionMenuService::menus($menu_ids);
            $info['menu_ids'] = $menu_ids;

            PromotionUserCache::set($id, $info);
        }

        if ($role) {
            $user_menu_ids = $info['menu_ids'] ?? [];
            $role_menu_ids = PromotionRoleService::menu_ids($info['role_ids'], where_disdel());

            $menu_list = PromotionMenuService::list('list', [where_delete()], [], 'menu_id,menu_pid,menu_name,menu_url,is_unlogin,is_unauth');
            foreach ($menu_list as &$val) {
                $val['is_check'] = 0;
                $val['is_role'] = 0;
                foreach ($user_menu_ids as $m_menu_id) {
                    if ($val['menu_id'] == $m_menu_id) {
                        $val['is_check'] = 1;
                    }
                }
                foreach ($role_menu_ids as $g_menu_id) {
                    if ($val['menu_id'] == $g_menu_id) {
                        $val['is_role'] = 1;
                    }
                }
            }
            $info['menu_tree'] = list_to_tree($menu_list, 'menu_id', 'menu_pid');
        }

        return $info;
    }

    /**
     * 用户添加
     *
     * @param array $param 用户信息
     * 
     * @return array|Exception
     */
    public static function add($param)
    {
        $model = new PromotionUserModel();
        $pk = $model->getPk();

        unset($param[$pk]);
        $create_uid = user_id();
        if($create_uid<=0){
            $create_uid = promotion_user_id();
        }
        $param['create_uid']  = $create_uid;
        $param['create_time'] = datetime();
        // 密码
        if (isset($param['password'])) {
            $param['password'] = password_hash($param['password'], PASSWORD_BCRYPT);
        }

        // 启动事务
        $model->startTrans();
        try {
            $param = self::commission_ratio_handle($param);
            //生成邀请码
            $param['invitation_code'] = $model->generate_invitation_code();
            // 添加
            $model->save($param);
            // 添加角色
            if (isset($param['role_ids'])) {
                $model->roles()->saveAll($param['role_ids']);
            }
            // 提交事务
            $model->commit();
        } catch (\Exception $e) {
            $errmsg = $e->getMessage();
            // 回滚事务
            $model->rollback();
        }

        if (isset($errmsg)) {
            exception($errmsg);
        }

        $param[$pk] = $model->$pk;
        PromotionUserCache::clear();
        return $param;
    }

    /**
     * 抽成比例加工
     * @Author: 易军辉
     * @DateTime:2024-07-18 20:30
     * @param $param
     * @return mixed
     */
    private static function commission_ratio_handle($param)
    {
        if(!isset($param['pid'])){
            return $param;
        }
        //查询等级
        $level= self::getLevel($param['pid']);
        $param['level'] =$level;
        if($param['level']>2){
            exception("暂只支持三级推广");
        }
        //处理抽成比例
        $commission_ratio = SettingService::info('commission_ratio_one,commission_ratio_two,commission_ratio_three');
        switch ($param['level']){
            case 0:
                if($param['commission_ratio']>$commission_ratio['commission_ratio_one']){
                    exception('一级推广员提成比例不能超过'.$commission_ratio['commission_ratio_one']."%");
                }
                $param['p_commission_ratio'] = 0;
                //查询角色
                $role_id = PromotionRoleService::getRoleIdByCode('one');
                if ($role_id){
                    $param['role_ids'] = [$role_id];
                }else{
                    exception('请添加一级推广员角色');
                }
                break;
            case 1:
                $p_promoter =PromotionUserModel::find($param['pid']);
                if($param['commission_ratio']>$p_promoter['commission_ratio'] || $param['commission_ratio']<$commission_ratio['commission_ratio_two']){
                    exception('二级推广员提成比例区间'.$commission_ratio['commission_ratio_two'].'%至'.$p_promoter['commission_ratio']."%");
                }
                $param['p_commission_ratio'] = bcsub($p_promoter['commission_ratio'], $param['commission_ratio'],0);
                //查询角色
                $role_id = PromotionRoleService::getRoleIdByCode('two');
                if ($role_id){
                    $param['role_ids'] = [$role_id];
                }else{
                    exception('请添加二级推广员角色');
                }
                break;
            case 2:
                $p_promoter =PromotionUserModel::find($param['pid']);
                if($param['commission_ratio']>$p_promoter['commission_ratio'] || $param['commission_ratio']<$commission_ratio['commission_ratio_three']){
                    exception('三级推广员提成比例区间'.$commission_ratio['commission_ratio_three'].'%至'.$p_promoter['commission_ratio'].'%');
                }
                $param['p_commission_ratio'] = bcsub($p_promoter['commission_ratio'], $param['commission_ratio'],0);
                //查询角色
                $role_id = PromotionRoleService::getRoleIdByCode('three');
                if ($role_id){
                    $param['role_ids'] = [$role_id];
                }else{
                    exception('请添加三级推广员角色');
                }
                break;
            default:
                $p_promoter =PromotionUserModel::find($param['pid']);
                if($param['commission_ratio']>$p_promoter['commission_ratio']){
                    exception('三级以上推广员提成比例不能大于'.$p_promoter['commission_ratio'].'%');
                }
                $param['p_commission_ratio'] = bcsub($p_promoter['commission_ratio'], $param['commission_ratio'],0);
                //查询角色
                $role_id = PromotionRoleService::getRoleIdByCode('three');
                if ($role_id){
                    $param['role_ids'] = [$role_id];
                }else{
                    exception('请添加三级推广员角色');
                }
                break;
        }
        return $param;
    }
    /**
     * 查询推广员等级
     * @Author: 易军辉
     * @DateTime:2024-07-18 20:11
     * @param $id 上级id
     * @return int|mixed
     */
    public static function getLevel($id)
    {
        if(!$id){
            return 0;
        }
        // 获取推广员信息
        $promoter =PromotionUserModel::find($id);
        if (!$promoter) {
            return 0;
        }
        // 递归计算推广员层级
        return self::calculateLevel($promoter->pid, 1);
    }

    private static function calculateLevel($pid, $level)
    {
        if ($pid == 0) {
            return $level;
        }

        $parentPromoter = PromotionUserModel::find($pid);
        if (!$parentPromoter) {
            return $level;
        }

        return self::calculateLevel($parentPromoter->pid, $level + 1);
    }
    /**
     * 用户修改
     *
     * @param int|array $ids   用户id
     * @param array     $param 用户信息
     * 
     * @return array|Exception
     */
    public static function edit($ids, $param = [])
    {
        $model = new PromotionUserModel();
        $pk = $model->getPk();

        unset($param[$pk], $param['ids']);
        $update_uid = user_id();
        if($update_uid<=0){
            $update_uid = promotion_user_id();
        }
        $param['update_uid']  = $update_uid;
        $param['update_time'] = datetime();
        // 密码
        if (isset($param['password'])) {
            $param['password'] = password_hash($param['password'], PASSWORD_BCRYPT);
        }

        // 启动事务
        $model->startTrans();
        try {
            if (is_numeric($ids)) {
                $ids = [$ids];
            }
            // 修改
            $param = self::commission_ratio_handle($param);
            $model->where($pk, 'in', $ids)->update($param);
            if (var_isset($param, ['role_ids'])) {
                foreach ($ids as $id) {
                    $info = $model->find($id);
                    // 修改角色
                    if (isset($param['role_ids'])) {
                        $info = $info->append(['role_ids']);
                        relation_update($info, $info['role_ids'], $param['role_ids'], 'roles');
                    }
                }
            }
            // 提交事务
            $model->commit();
        } catch (\Exception $e) {
            $errmsg = $e->getMessage();
            // 回滚事务
            $model->rollback();
        }

        if (isset($errmsg)) {
            exception($errmsg);
        }

        $param['ids'] = $ids;

        PromotionUserCache::clear();

        return $param;
    }

    /**
     * 用户删除
     *
     * @param int|array $ids  用户id
     * @param bool      $real 是否真实删除
     * 
     * @return array|Exception
     */
    public static function dele($ids, $real = false)
    {
        $model = new PromotionUserModel();
        $pk = $model->getPk();

        // 启动事务
        $model->startTrans();
        try {
            if (is_numeric($ids)) {
                $ids = [$ids];
            }
            if ($real) {
                foreach ($ids as $id) {
                    $info = $model->find($id);
                    // 删除部门
                    $info->depts()->detach();
                    // 删除职位
                    $info->posts()->detach();
                    // 删除角色
                    $info->roles()->detach();
                }
                $model->where($pk, 'in', $ids)->delete();
            } else {
                $update = delete_update();
                $model->where($pk, 'in', $ids)->update($update);
            }
            // 提交事务
            $model->commit();
        } catch (\Exception $e) {
            $errmsg = $e->getMessage();
            // 回滚事务
            $model->rollback();
        }

        if (isset($errmsg)) {
            exception($errmsg);
        }

        $update['ids'] = $ids;

        PromotionUserCache::del($ids);
        PromotionUserCache::delToken($ids);

        return $update;
    }

    /**
     * 用户登录
     *
     * @param array $param 登录信息
     * @Apidoc\Returned("AdminToken", type="string", require=true, desc="AdminToken")
     * @return array|Exception
     */
    public static function login($param)
    {
        $model = new PromotionUserModel();
        $pk = $model->getPk();

        $field = $pk . ',password,is_disable,login_num';

        if (Validate::rule('username', 'mobile')->check($param)) {
            $where[] = ['phone', '=', $param['username']];
        } else if (Validate::rule('username', 'email')->check($param)) {
            $where[] = ['email', '=', $param['username']];
        } else {
            $where[] = ['username', '=', $param['username']];
        }
        $where[] = where_delete();

        $user = $model->field($field)->where($where)->find();
        if (empty($user)) {
            $user = $model->field($field)->where(where_delete(['username|phone|email', '=', $param['username']]))->find();
        }
        if (empty($user)) {
            exception('账号或密码错误');
        }

        $user = $user->toArray();
        $password_verify = password_verify($param['password'], $user['password']);
        if (!$password_verify) {
            exception('账号或密码错误');
        }
        if ($user['is_disable'] == 1) {
            exception('账号已被禁用，请联系管理员');
        }

        $promotion_user_id = $user[$pk];
        $ip_info = Utils::ipInfo();

        $update['login_ip']     = $ip_info['ip'];
        $update['login_region'] = $ip_info['region'];
        $update['login_time']   = datetime();
        $update['login_num']    = $user['login_num'] + 1;
        $model->where($pk, $promotion_user_id)->update($update);

        $user_log[$pk]             = $promotion_user_id;
        $user_log['response_code'] = 200;
        $user_log['response_msg']  = '登录成功';
        PromotionUserLogService::add($user_log, PromotionSettingService::LOG_TYPE_LOGIN);

        PromotionUserCache::del($promotion_user_id);
        $user = self::info($promotion_user_id);
        $data = self::loginField($user);

        return $data;
    }

    /**
     * 用户登录返回字段
     *
     * @param array $user 用户信息
     *
     * @return array
     */
    public static function loginField($user)
    {
        $data = [];
        $setting = PromotionSettingService::info();
        $token_name = $setting['token_name'];
        $user[$token_name] = self::token($user);
        $fields = ['promotion_user_id', 'nickname', 'username', $token_name];
        foreach ($fields as $field) {
            if (isset($user[$field])) {
                $data[$field] = $user[$field];
            }
        }

        return $data;
    }

    /**
     * 用户token
     *
     * @param  array $user 用户信息
     *
     * @return string
     */
    public static function token($user)
    {
        $token = PromotionUserTokenService::create($user);
        $setting = PromotionSettingService::info();
        $ttl = $setting['token_exp'] * 3600;
        PromotionUserCache::setToken($user['promotion_user_id'], $token, $ttl);
        return $token;
    }

    /**
     * 用户退出
     *
     * @param int $id 用户id
     * 
     * @return array
     */
    public static function logout($id)
    {
        $model = new PromotionUserModel();
        $pk = $model->getPk();

        $update['logout_time'] = datetime();

        $model->where($pk, $id)->update($update);

        $update[$pk] = $id;

        PromotionUserCache::del($id);
        PromotionUserCache::delToken($id);

        return $update;
    }

    /**
     * 获取指定推广员的所有下级ID
     * @Author: 易军辉
     * @DateTime:2024-07-22 14:49
     * @param $rootId
     * @return array
     */
    public static function getAllDescendants($rootId)
    {
        $allDescendants = [];

        // 递归查询函数
        $getDescendants = function($parentId) use (&$getDescendants, &$allDescendants) {
            $children = Db::name('promotion_user')
                ->where('pid', $parentId)
                ->where('is_disable',0)
                ->where('is_delete',0)
                ->column('promotion_user_id');

            foreach ($children as $childId) {
                $allDescendants[] = $childId;
                $getDescendants($childId);
            }
        };

        // 开始递归查询
        $getDescendants($rootId);

        return $allDescendants;
    }

    /**
     * 查询我的下级页面参数
     * @Author: 易军辉
     * @DateTime:2024-07-23 10:03
     */
    public static function getParams()
    {
        $userModel = PromotionUserModel::where('promotion_user_id',promotion_user_id())->field('level,commission_ratio')->find();
        //处理抽成比例
        $commission_ratio = SettingService::info('commission_ratio_one,commission_ratio_two,commission_ratio_three');
        $level = $userModel['level']+1;
        $min_commission_ratio = 0;
        switch ($level){
            case 0:
                $min_commission_ratio = $commission_ratio['commission_ratio_one'];
                break;
            case 1:
                $min_commission_ratio = $commission_ratio['commission_ratio_two'];
                break;
            case 2:
                $min_commission_ratio = $commission_ratio['commission_ratio_three'];
                break;
            default:
                $min_commission_ratio = $commission_ratio['commission_ratio_three'];
                break;
        }
        return [
            'commission_ratio'=>$userModel['commission_ratio'],
            'max_commission_ratio'=>(int)bcsub($userModel['commission_ratio'], $min_commission_ratio,0),
            'min_commission_ratio'=>$min_commission_ratio,
        ];
    }

    /**
     * 推广员提现
     * @Author: 易军辉
     * @DateTime:2024-07-24 18:42
     * @param $money 提现金额
     * @param $title 提现名称
     * @param $data_id 关联表ID
     * @param $remark 备注
     */
    public static function withdrawal($money=0,$title="",$data_id=null,$remark=null)
    {
        $proModel = new PromotionUserModel();
        $promotion_user_id = promotion_user_id(true);
        $pro_money = $proModel->where($proModel->getPk(),$promotion_user_id)->field($proModel->getPk().',balance')->find();
        if($pro_money['balance']<$money){
            exception("您的本金".$pro_money['balance']."不足，无法提现");
        }
        $model = new PromotionBillModel();
        $pk = $model->getPk();
        $param = array(
            'create_uid'=>$promotion_user_id,
            'create_time'=>datetime(),
            'promotion_user_id'=>$promotion_user_id,
            'money'=>-$money,//操作金额
            'balance'=>bcsub($pro_money['balance'],$money,2),//余额
            'type'=>PromotionBillModel::getTypes('withdrawal',1),
            'data_id'=>$data_id,
            'title'=>$title,
            'remark'=>$remark,
        );
        // 启动事务
        $model->startTrans();
        try {
            $model->save($param);
            $id = $model->$pk;
            if (empty($id)) {
                exception();
            }
            $param[$pk] = $id;
            $res = $proModel->where($proModel->getPk(),$promotion_user_id)->update(['balance'=>bcsub($pro_money['balance'],$money,2)]);
            if (empty($res)) {
                exception('提现失败');
            }
            // 提交事务
            $model->commit();
        } catch (\Exception $e) {
            $errmsg = $e->getMessage();
            // 回滚事务
            $model->rollback();
        }

        if (isset($errmsg)) {
            exception($errmsg);
        }

        return $param;
    }

    /**
     * 推广员收入
     * @Author: 易军辉
     * @DateTime:2024-09-12 17:03
     * @param $promotion_user_id 推广员id
     * @param $money 金额
     * @param $title 收入名称
     * @param $data_id 关联id
     * @param $remark 备注
     * @param $mer_id 商家id
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function income($promotion_user_id=null,$money=0,$title="",$data_id=null,$remark=null,$mer_id=0)
    {
        //推广员ID
        if(!$promotion_user_id){
            $promotion_user_id = promotion_user_id(true);
        }
        //创建用户ID
        $create_uid = promotion_user_id();
        if($create_uid<=0){
            $create_uid = user_id();
        }
        if($create_uid<=0){
            $create_uid = mer_user_id();
        }
        $proModel = new PromotionUserModel();
        $pro_money = $proModel->where($proModel->getPk(),$promotion_user_id)->field($proModel->getPk().',balance')->find();
        $model = new PromotionBillModel();
        $pk = $model->getPk();
        $param = array(
            'create_uid'=>$create_uid,
            'create_time'=>datetime(),
            'promotion_user_id'=>$promotion_user_id,
            'mer_id'=>$mer_id,
            'money'=>$money,
            'balance'=>bcadd($pro_money['balance'],$money,2),//余额
            'type'=>PromotionBillModel::getTypes('commission',1),
            'data_id'=>$data_id,
            'title'=>$title,
            'remark'=>$remark,
        );
        // 启动事务
        $model->startTrans();
        try {
            $model->save($param);
            $id = $model->$pk;
            if (empty($id)) {
                exception();
            }
            $param[$pk] = $id;
            $res = $pro_money->where($proModel->getPk(),$promotion_user_id)->update([
                'balance'=>bcadd($pro_money['balance'],$money,2)]);
            if (empty($res)) {
                exception('发放失败');
            }
            // 提交事务
            $model->commit();
        } catch (\Exception $e) {
            $errmsg = $e->getMessage();
            // 回滚事务
            $model->rollback();
        }

        if (isset($errmsg)) {
            exception($errmsg);
        }

        return $param;
    }
    /**
     * 退款给推广员
     * @Author: 易军辉
     * @DateTime:2024-06-14 15:42
     * @param $promotion_user_id 推广员ID
     * @param $money 收入金额
     * @param $title 收入名称
     * @param $data_id 关联表ID
     * @param $remark 备注
     */
    public static function refund($promotion_user_id=null,$money=0,$title="",$data_id=null,$remark=null)
    {
        //推广员ID
        if(!$promotion_user_id){
            $promotion_user_id = promotion_user_id(true);
        }
        //创建用户ID
        $create_uid = promotion_user_id();
        if($create_uid<=0){
            $create_uid = user_id();
        }
        $proModel = new PromotionUserModel();
        $pro_money = $proModel->where($proModel->getPk(),$promotion_user_id)->field($proModel->getPk().',balance')->find();
        $model = new PromotionBillModel();
        $pk = $model->getPk();
        $param = array(
            'create_uid'=>$create_uid,
            'create_time'=>datetime(),
            'promotion_user_id'=>$promotion_user_id,
            'money'=>$money,
            'balance'=>bcadd($pro_money['balance'],$money,2),//余额
            'type'=>PromotionBillModel::getTypes('refund',1),
            'data_id'=>$data_id,
            'title'=>$title,
            'remark'=>$remark,
        );
        // 启动事务
        $model->startTrans();
        try {
            $model->save($param);
            $id = $model->$pk;
            if (empty($id)) {
                exception();
            }
            $param[$pk] = $id;
            $res = $pro_money->where($proModel->getPk(),$promotion_user_id)->update([
                'balance'=>bcadd($pro_money['balance'],$money,2)]);
            if (empty($res)) {
                exception('退款失败');
            }
            // 提交事务
            $model->commit();
        } catch (\Exception $e) {
            $errmsg = $e->getMessage();
            // 回滚事务
            $model->rollback();
        }

        if (isset($errmsg)) {
            exception($errmsg);
        }

        return $param;
    }

    /**
     * 推广员支出(如订单撤销退款)
     * @Author: 易军辉
     * @DateTime:2024-09-23 21:17
     * @param $promotion_user_id 推广员ID
     * @param $money 消费金额
     * @param $title 消费名称
     * @param $data_id 管理表id
     * @param $remark 备注
     * @param $mer_id 商家ID
     * @param $order_id   订单ID
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function consumption($promotion_user_id,$money=0,$title="",$data_id=null,$remark=null,$mer_id=0,$order_id=0)
    {
        $proModel = new PromotionUserModel();
        $pro_money = $proModel->where($proModel->getPk(),$promotion_user_id)->field($proModel->getPk().',balance,income')->find();
        if($pro_money['balance']<$money){
            exception("推广员ID:".$promotion_user_id."的余额".$pro_money['balance']."不足，请充值");
        }
        //创建用户ID
        $create_uid = promotion_user_id();
        if($create_uid<=0){
            $create_uid = user_id();
        }
        if($create_uid<=0){
            $create_uid = mer_user_id();
        }
        $model = new PromotionBillModel();
        $pk = $model->getPk();
        $param = array(
            'create_uid'=>$create_uid,
            'create_time'=>datetime(),
            'promotion_user_id'=>$promotion_user_id,
            'mer_id'=>$mer_id,
            'money'=>-$money,
            'balance'=>bcsub($pro_money['balance'],$money,2),//余额
            'type'=>PromotionBillModel::getTypes('refund',1),
            'shop_order_id'=>$order_id,
            'data_id'=>$data_id,
            'title'=>$title,
            'remark'=>$remark,
        );
        // 启动事务
        $model->startTrans();
        try {
            $model->save($param);
            $id = $model->$pk;
            if (empty($id)) {
                exception();
            }
            $param[$pk] = $id;
            $res = $pro_money->where($proModel->getPk(),$promotion_user_id)->update([
                'balance'=>bcsub($pro_money['balance'],$money,2)]);
            if (empty($res)) {
                exception('支付失败');
            }
            // 提交事务
            $model->commit();
        } catch (\Exception $e) {
            $errmsg = $e->getMessage();
            // 回滚事务
            $model->rollback();
        }

        if (isset($errmsg)) {
            exception($errmsg);
        }

        return $param;
    }

    /**
     * 根据邀请码查询推广员id
     * @Author: 易军辉
     * @DateTime:2024-07-26 17:51
     * @param $invitation_code
     */
    public static function getUserIdByCode($invitation_code)
    {
        if(!$invitation_code){
            return null;
        }
        $proModel = new PromotionUserModel();
        return $proModel->where('invitation_code',$invitation_code)->order('promotion_user_id desc')->value($proModel->getPk());
    }

    /**
     * 查询邀请链接
     * @Author: 易军辉
     * @DateTime:2024-07-26 19:15
     * @return mixed
     */
    public static function getInvitationLink($domain)
    {
        $setting = SettingService::info('mer_website');
        $url =$domain;
        if(isset($setting['mer_website']) && $setting['mer_website']){
            $url = $setting['mer_website'];
        }
        //查询邀请码
        $proModel = new PromotionUserModel();
        $invitation_code = $proModel->where($proModel->getPk(),promotion_user_id())->value('invitation_code');
        //若没有邀请码，重新生成
        if(!$invitation_code){
            $invitation_code = $proModel->generate_invitation_code();
            $edit_res = $proModel->where($proModel->getPk(),promotion_user_id())->update(['invitation_code'=>$invitation_code]);
        }
        $url .="/register?code=".$invitation_code;
        return $url;
    }
}
